package sh.orm;

import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import sh.orm.annotation.*;
import sh.orm.cache.CacheManager;
import sh.orm.convert.JdbcType;
import sh.orm.util.NameUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 静态的Entity，只添加静态信息,
 * 初始化：
 * @author lqq
 * @date 2019/1/24
 */
@Data
@Slf4j
public class StaticEntity {

    private String entityName;

    /** 数据库名称 */
    private String tableName;

    private Map<String,String> fieldColumnMap = new HashMap<>();;

    private Map<String,String> columnFieldMap = new HashMap<>();

    /** 属性上面的注解 */
    private Map<String , Annotation[]> fieldAnnotationsMap = new HashMap<>();

    /** orm中拦截的方法和对应的注解，因为只需要一次拦截，所以只要得到一个注解即可 */
    private Map<String , Annotation> queryMethodAnnotationMap = new HashMap<>();

    /** 属性上面，有关联关系的注解 key:属性 ，value 关联关系注解 ，用于代理对象中拦截查询*/
    private Map<String , Annotation[]> fieldRelationAnnotationsMap = new HashMap<>();

    /** 有关联关系的注解 */
    private static Set<Class<?>> relationAnnotationSet = new HashSet<Class<?>>();



    StaticEntity(Class<?> clazz){
        //所有有关联关系的注解，即 有@Relation 注解
        relationAnnotationSet.add(OneToOne.class);
        relationAnnotationSet.add(OneToMany.class);
        relationAnnotationSet.add(ManyToOne.class);
        relationAnnotationSet.add(ManyToMany.class);

        init(clazz);

       //    表明
        tableName = "t_" + NameUtil.convertHumpToUnderline(clazz.getSimpleName());


    }


    /**
     * 初始化
     * 递归把所有的属性转换为 column-field map 的形式
     * @param clazz
     */
    private void init(Class<?> clazz){
        Field[] fields = clazz.getDeclaredFields();
        List<Annotation> tempRelationAnnotations = new ArrayList<>();
        for(Field field : fields){
            field.setAccessible(true);

            //TODO 通过 @Relation 进行判断
            // get方法名 和 对应的关联查询注解
            for(Annotation annotation : field.getAnnotations()){
                if(relationAnnotationSet.contains(annotation.annotationType())){
                    queryMethodAnnotationMap.put(NameUtil.getGetNameByFieldName(field.getName()),annotation);
                    break;
                }
            }
            // 判断属性上面关联关系的注解，把所有关联关系保存起来
            //注解的继承关系 TODO
            tempRelationAnnotations.clear();
            for(Annotation annotation : field.getAnnotations()){
                if(relationAnnotationSet.contains(annotation.annotationType())){
                    tempRelationAnnotations.add(annotation);
                }
            }
            if(tempRelationAnnotations.size() > 0){
                Annotation[] annotations = new Annotation[tempRelationAnnotations.size()];
                for(int i = 0; i < tempRelationAnnotations.size(); i++){
                    annotations[i] = tempRelationAnnotations.get(i);
                }
                fieldRelationAnnotationsMap.put(field.getName(), annotations);
            }

            //属性名 和 注解
            if(field.getAnnotations().length > 0){
                fieldAnnotationsMap.put(field.getName(),field.getAnnotations());
            }


            //TRANSIENT: 128 （二进制 1000 0000）
            //这里的 或与非操作，最终判断有transient修饰符跳过
            int modifier = field.getModifiers();
            if((modifier & 128) == 128){
                //如果有transient，跳过
                continue;
            }
            columnFieldMap.put(NameUtil.convertHumpToUnderline(field.getName()),field.getName());
        }

        if(!"Object".equals(clazz.getSuperclass().getSimpleName())){
            init(clazz.getSuperclass());
        }
    }


}
